package pessoa;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import database.Database;
import estoque.Estoque;
import excecoes.CpfCnpjInvalidoException;
import excecoes.RegistroComDependenciaException;


/**
 * Esta classe e responsavel por manter os clientes, executando as operacoes de
 * cadastrar, excluir,alterar, pesquisar e recuperar-los
 * 
 */
public class RepositorioFornecedor {

	private Connection conexao;

	/**
	 * Esse construtor atribui uma conexao ao atributo conexao da classe
	 */
	public RepositorioFornecedor(){

		conexao = Database.getConexao();

	}

	/**
	 * Esse metodo deve cadastrar um fornecedor, registrando-o no banco de dados,
	 * 
	 * @param fornecedor
	 * 
	 */
	public void cadastrar(Fornecedor fornecedor){
		
		/*
		 * Se o fornecedor passado for null, lanca uma excecao
		 */
		if(fornecedor == null){
			throw new RuntimeException("Fornecedor nulo");
		}
		
		/*
		 * String contendo o comando o codigo sql q sera executado, os valores devem
		 * corresponder as colunas. Cada valor e marcado com uma ? e sera preenchido
		 * posteriormente pelos metodos set do statement
		 */
		String sql = "INSERT INTO fornecedor (cnpj, nome, endereco, email, telefone)" +
				" VALUES (?,?,?,?,?);";

		try{
			
			PreparedStatement statement = conexao.prepareStatement(sql);

			/*
			 * Determina os valores que substituirao as ? no comando sql q sera executado
			 */
			statement.setString(1, fornecedor.getCnpj());
			statement.setString(2, fornecedor.getNome());
			statement.setString(3, fornecedor.getEndereco());
			statement.setString(4, fornecedor.getEmail());
			statement.setString(5, fornecedor.getTelefone());
			
			/*
			 * Executa e fecha o statemente
			 */
			statement.execute();
			statement.close();

		}catch (SQLException e) {
			
			e.printStackTrace();
			
			/*
			 * relanca a exececao como uma RuntimeException indicando onde ocorreu o erro
			 */
			throw new RuntimeException("Falha ao cadastrar fornecedor");

		}

	}//cadastrar(Fornecedor fornecedor)

	/**
	 * Esse metodo deve excluir um fornecedor, removendo-o do banco de dados.
	 * Um fornecedor nao pode ser excluido se algum produto depender dele
	 * 
	 * @throws RegistroComDependenciaException - se houver algum produto que dependa do fornecedor
	 */
	public void excluir(String cnpj) throws RegistroComDependenciaException{
		
		/*
		 * Se o cnpj passado for null, laca uma excecao
		 */
		if(cnpj == null){

			throw new RuntimeException("String nula");

		}
		
		Estoque estoque = new Estoque();
		
		/*
		 * Se nao houver nenhum fornecedor com o cnpj informado o metodo pesquisar
		 * retornara null
		 */
		if(pesquisar(cnpj) != null){
			
			/*
			 * Se houver algum produto que dependa do fornecedor, ele nao pode ser 
			 * excluido 
			 */
			if(	estoque.temProduto(cnpj) == false){

				String sql = "DELETE FROM fornecedor WHERE cnpj=?";

				try{

					PreparedStatement statement = conexao.prepareStatement(sql);

					statement.setString(1, cnpj);

					statement.execute();
					statement.close();

				}catch (SQLException e) {

					e.printStackTrace();

					throw new RuntimeException("Falha ao excluir fornecedor");
				}
			}
		}else{

			throw new RegistroComDependenciaException("Nao foi possivel excluir o fornecedor," +
					" um ou mais produto depende dele");

		}
	}//excluir(String cnpj)

	/**
	 * Esse metodo deve atualizar os atributos de um fornecedor.
	 * 
	 * O fornecedor nao deve ser alterado caso possua algum produto
	 * Nao se deve alterar o codigo do produto
	 * 
	 * @param  fornecedor
	 * 
	 * @throws RegistroComDependenciaException 
	 */
	public void atualizar(Fornecedor fornecedor) throws RegistroComDependenciaException{
		

		if(fornecedor == null){

			throw new RuntimeException("fornecedor nulo");

		}
		
		System.out.println("fornecedor nao nulo");
		
		Estoque estoque = new Estoque();
		
		if(pesquisar(fornecedor.getCnpj()) != null){
			
			System.out.println("A pesquisa pelo cnpj retornou\n\n" + pesquisar(fornecedor.getCnpj()));
			
			if(estoque.temProduto(fornecedor.getCnpj()) == false){

				String sql = "UPDATE fornecedor SET nome=?, endereco=?, email=?, telefone=? WHERE cnpj=?;";

				try{

					PreparedStatement statement = conexao.prepareStatement(sql);

					statement.setString(1, fornecedor.getNome());
					statement.setString(2, fornecedor.getEndereco());
					statement.setString(3, fornecedor.getEmail());
					statement.setString(4, fornecedor.getTelefone());
					statement.setString(5, fornecedor.getCnpj());
				
					statement.execute();
					System.out.println("Statemente executado");
					statement.close();

				}catch (SQLException e) {

					e.printStackTrace();

					throw new RuntimeException("Falha ao atualizar fornecedor");
				}
			}
		}else{

			throw new RegistroComDependenciaException("Nao foi possivel excluir o fornecedor," +
					" um ou mais produto depende dele");

		}

		
		
	}

	/**
	 * Esse metodo deve pesquisar um fornecedor no banco de dados e retorna-lo
	 * 
	 * @param cnpj
	 * 
	 * @return Um objeto fornecedor
	 */
	public Fornecedor pesquisar(String cnpj){

		if(cnpj == null){
			
			throw new RuntimeException("String nula");
			
		}

		Fornecedor fornecedor = null;

		for(Fornecedor F : recuperarFornecedores()){

			if(F.getCnpj().equals(cnpj)){

				fornecedor = F;

			}
		}

		return fornecedor;

	}//pesquisar(String cnpj)

	/**
	 * Esse metodo deve retornar todos os fornecedores contidos no banco de dados
	 * 
	 * @return Arraylist<Forncedor> contendo todos os fornecedores cadastrados
	 */
	public ArrayList<Fornecedor> recuperarFornecedores(){

		ArrayList<Fornecedor> fornecedores = new ArrayList<>();

		try {

			String sql = "SELECT * FROM fornecedor;";

			PreparedStatement statement = conexao.prepareStatement(sql);

			ResultSet result = statement.executeQuery();

			/*
			 * recupera todos os dados da tabela, transfere para um objeto fornecedor
			 * e adiciona o objeto no arraylist
			 */
			while(result.next()){

				fornecedores.add(new Fornecedor(result.getString("cnpj"), result.getString("nome"),
						result.getString("endereco"), result.getString("email"),
						result.getString("telefone")));

			} 

			/*
			 * Fecha o ResultSet e o Statement
			 */
			result.close();
			statement.close();

		} catch (SQLException e) {

			e.printStackTrace();

			throw new RuntimeException("Falha ao recuperar fornecedores");

		} catch (CpfCnpjInvalidoException e) {

			e.printStackTrace();
		}

		return fornecedores;

	}//recuperarFornecedores()

}//RepositorioFornecedor
